﻿namespace Contoso.ActiveDirectory {

    #region Usings
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    #endregion

    [Serializable]
    public class ExchangeMailboxAttributes : IExchangeMailboxAttributes {

        #region Members
        public static readonly string[] AttributesToGet;

        public string DatabaseName {
            get {
                databaseName = string.Empty;
                if (!string.IsNullOrWhiteSpace(this.HomeMDB)) {
                    if (this.HomeMDB.IndexOf(",CN=Databases", StringComparison.OrdinalIgnoreCase) > 0) {
                        databaseName = this.HomeMDB.Substring(0, this.HomeMDB.IndexOf(",CN=Databases", StringComparison.OrdinalIgnoreCase)).Replace("CN=", string.Empty);
                    }
                }
                return databaseName;
            }
        }
        private string databaseName;

        public IExchangeActiveSyncDevices ExchangeActiveSyncDevices { get; private set; }

        public string HomeMDB { get; private set; }

        public string HomeMTA { get; private set; }

        public int MDBOverHardQuotaLimit { get { return mdbOverHardQuotaLimit; } }
        private int mdbOverHardQuotaLimit;

        public int MDBOverQuotaLimit { get { return mdbOverQuotaLimit; } }
        private int mdbOverQuotaLimit;

        public int MDBStorageQuota { get { return mdbStorageQuota; } }
        private int mdbStorageQuota;

        public int MDBUnreadLimit { get { return mdbUnreadLimit; } }
        private int mdbUnreadLimit;

        public bool MDBUseDefaults { get { return mdbUseDefaults; } }
        private bool mdbUseDefaults;

        /// <summary>
        /// Exchange Litigation Control flags
        /// </summary>
        public MSExchELCMailboxFlags MSExchELCMailboxFlags { get { return msExchELCMailboxFlags; } }
        private MSExchELCMailboxFlags msExchELCMailboxFlags;

        public string MSExchHomeServerName { get; private set; }

        public DateTime? MSExchLitigationHoldDate { get { return msExchLitigationHoldDate; } }
        private DateTime? msExchLitigationHoldDate;

        public string MSExchLitigationHoldOwner { get; private set; }

        public Guid MSExchMailboxGuid { get { return msExchMailboxGuid; } }
        private Guid msExchMailboxGuid;

        /// <summary>
        /// Defines if the mailbox is managed for Outlook Mobile Access (ActiveSync)
        /// </summary>
        public MSExchMobileMailboxFlags MSExchMobileMailboxFlags { get { return msExchMobileMailboxFlags; } }
        private MSExchMobileMailboxFlags msExchMobileMailboxFlags;

        public DateTime? MSExchWhenMailboxCreated { get { return msExchWhenMailboxCreated; } }
        private DateTime? msExchWhenMailboxCreated;

        public IReadOnlyList<string> MSExchOmaAdminExtendedSettings { get; private set; }

        public MSExchangeOMAWirelessEnable MSExchOmaAdminWirelessEnable { get { return msExchOmaAdminWirelessEnable; } }
        private MSExchangeOMAWirelessEnable msExchOmaAdminWirelessEnable;

        public MSExchRemoteRecipientType MSExchRemoteRecipientType { get { return msExchRemoteRecipientType; } }
        private MSExchRemoteRecipientType msExchRemoteRecipientType;

        public MSExchUserAccountControl MSExchUserAccountControl { get { return msExchUserAccountControl; } }
        private MSExchUserAccountControl msExchUserAccountControl;

        public IReadOnlyList<string> ProtocolSettings { get; private set; }

        /// <summary>
        /// The list of distinguished names that may send on behalf of this mailbox
        /// </summary>
        public IReadOnlyList<string> PublicDelegates { get; private set; }

        public string ServerName {
            get {
                serverName = string.Empty;
                if (!string.IsNullOrWhiteSpace(this.MSExchHomeServerName)) {
                    if (this.MSExchHomeServerName.IndexOf("/CN=", StringComparison.OrdinalIgnoreCase) > 0) {
                        serverName = this.MSExchHomeServerName.Substring(this.MSExchHomeServerName.LastIndexOf("CN=", StringComparison.OrdinalIgnoreCase));
                        if (serverName.Length > "/CN=".Length) {
                            serverName = serverName.Substring("/CN=".Length - 1);
                        }
                    }
                }
                return serverName;
            }
        }
        private string serverName;
        #endregion

        #region Constructors
        static ExchangeMailboxAttributes() {
            AttributesToGet = new string[]
            {
                "homeMDB",
                "homeMTA",
                "mdbOverHardQuotaLimit",
                "mdbOverQuotaLimit",
                "mdbStorageQuota",
                "mdbUnreadLimit",
                "mdbUseDefaults",
                "msExchELCMailboxFlags",
                "msExchHomeServerName",
                "msExchLitigationHoldDate",
                "msExchLitigationHoldOwner",
                "msExchMailboxGuid",
                "msExchOmaAdminExtendedSettings",
                "msExchOmaAdminWirelessEnable",
                "msExchRemoteRecipientType",
                "msExchUserAccountControl",
                "msExchWhenMailboxCreated",
                "publicDelegates",
                "protocolSettings"
            };
        }
        public ExchangeMailboxAttributes() {
            this.ExchangeActiveSyncDevices = new ActiveDirectory.ExchangeActiveSyncDevices();
            this.HomeMDB = string.Empty;
            this.HomeMTA = string.Empty;
            this.MSExchHomeServerName = string.Empty;
            this.MSExchOmaAdminExtendedSettings = new List<string>();
            this.MSExchLitigationHoldOwner = string.Empty;
            this.PublicDelegates = new List<string>();
            this.ProtocolSettings = new List<string>();
        }
        #endregion

        #region Methods
        /// <summary>
        /// Requires elevated permissions due to the ExchangeActiveSyncDevices attribute is not normally visible to all users
        /// </summary>
        public void GetExchangeActiveSyncDevices(string dn) {
            string filter = string.Format("objectCategory={0}", Contoso.ActiveDirectory.ExchangeActiveSyncDevices.ObjectCategoryShortName);
            var devices = ADDataAccess.GetADObjectProperties<ExchangeActiveSyncDevices>(
                dn, null, filter, PartitionScope.LocalPartition);
            if ((devices != null) && (devices.Count > 0)) {
                this.ExchangeActiveSyncDevices = devices.FirstOrDefault();
            }
        }

        public void ProcessResults(Dictionary<string, object[]> attributes) {
            if (attributes.ContainsKey("homeMDB")) {
                this.HomeMDB = attributes["homeMDB"][0].ToString();
            }
            if (attributes.ContainsKey("homeMTA")) {
                this.HomeMTA = attributes["homeMTA"][0].ToString();
            }
            if (attributes.ContainsKey("MDBOverHardQuotaLimit")) {
                int.TryParse(attributes["MDBOverHardQuotaLimit"][0].ToString(), out mdbOverHardQuotaLimit);
            }
            if (attributes.ContainsKey("MDBOverQuotaLimit")) {
                int.TryParse(attributes["MDBOverQuotaLimit"][0].ToString(), out mdbOverQuotaLimit);
            }
            if (attributes.ContainsKey("MDBStorageQuota")) {
                int.TryParse(attributes["MDBStorageQuota"][0].ToString(), out mdbStorageQuota);
            }
            if (attributes.ContainsKey("MDBUnreadLimit")) {
                int.TryParse(attributes["MDBUnreadLimit"][0].ToString(), out mdbUnreadLimit);
            }
            if (attributes.ContainsKey("MDBUseDefaults")) {
                bool.TryParse(attributes["MDBUseDefaults"][0].ToString(), out mdbUseDefaults);
            }
            if (attributes.ContainsKey("msExchELCMailboxFlags")) {
                Enum.TryParse<MSExchELCMailboxFlags>(attributes["msExchELCMailboxFlags"][0].ToString(), out msExchELCMailboxFlags);
            }
            if (attributes.ContainsKey("msExchHomeServerName")) {
                this.MSExchHomeServerName = attributes["msExchHomeServerName"][0].ToString();
            }
            if (attributes.ContainsKey("msExchMobileMailboxFlags")) {
                Enum.TryParse<MSExchMobileMailboxFlags>(attributes["msExchMobileMailboxFlags"][0].ToString(), out msExchMobileMailboxFlags);
            }            
            if (attributes.ContainsKey("msExchOmaAdminWirelessEnable")) {
                Enum.TryParse<MSExchangeOMAWirelessEnable>(attributes["msExchOmaAdminWirelessEnable"][0].ToString(), out msExchOmaAdminWirelessEnable);
            }
            if (attributes.ContainsKey("msExchRemoteRecipientType")) {
                Enum.TryParse<MSExchRemoteRecipientType>(attributes["msExchRemoteRecipientType"][0].ToString(), out msExchRemoteRecipientType);
            }
            if (attributes.ContainsKey("msExchUserAccountControl")) {
                Enum.TryParse<MSExchUserAccountControl>(attributes["msExchUserAccountControl"][0].ToString(), out msExchUserAccountControl);
            }

            this.ProtocolSettings = ADDataAccess.GetMultiValuedAttribute<string>("protocolSettings", attributes);
            this.PublicDelegates = ADDataAccess.GetMultiValuedAttribute<string>("publicDelegates", attributes);

            this.MSExchOmaAdminExtendedSettings = ADDataAccess.GetMultiValuedAttribute<string>("msExchOmaAdminExtendedSettings", attributes);
            if (attributes.ContainsKey("msExchLitigationHoldDate")) {
                var tempMSExchLitigationHoldDate = DateTime.MinValue;
                if (DateTime.TryParse(attributes["msExchLitigationHoldDate"][0].ToString(), out tempMSExchLitigationHoldDate)) {
                    msExchLitigationHoldDate = tempMSExchLitigationHoldDate;
                }
            }
            if (attributes.ContainsKey("msExchLitigationHoldOwner")) {
                this.MSExchLitigationHoldOwner = attributes["msExchLitigationHoldOwner"][0].ToString();
            }
            if (attributes.ContainsKey("msExchMailboxGuid")) {
                if (attributes["msExchMailboxGuid"][0] as byte[] != null) {
                    msExchMailboxGuid = new Guid((byte[])attributes["msExchMailboxGuid"][0]);
                }
                else {
                    msExchMailboxGuid = new Guid(attributes["msExchMailboxGuid"][0].ToString().FromBase64());
                }
            }
            if (attributes.ContainsKey("msExchWhenMailboxCreated")) {
                var tempMSExchWhenMailboxCreated = DateTime.MinValue;
                if (DateTime.TryParse(attributes["msExchWhenMailboxCreated"][0].ToString(), out tempMSExchWhenMailboxCreated)) {
                    msExchWhenMailboxCreated = tempMSExchWhenMailboxCreated;
                }
            }
        }
        #endregion
    }
}
